﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Windows.Markup;
using System.Xaml;

using agree.schema;

using alib;
using alib.Debugging;
using alib.Enumerable;
using alib.Observable;
using alib.Character;

namespace agree
{
	///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	/// <summary>
	/// 
	/// </summary>
	///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	//[DebuggerDisplay("{ToString(),nq}")]
	//[XamlSetMarkupExtension("SetMarkupExt")]
	[UsableDuringInitialization(false)]
	public class StringCorpus : IdentList<IString>, ICorpus
	{
		public StringCorpus(IIdentity prv, IEnumerable<IString> items)
			: base(prv, items)
		{
		}
		public StringCorpus(IIdentity prv)
			: base(prv)
		{
		}
		public StringCorpus()
			: this(default(IIdentity))
		{
			throw not.valid;
		}

		///////////////////////////////////////////////////////////////////////
		/// 
		[DebuggerBrowsable(DebuggerBrowsableState.Never)]
		ItemCulture culture;
		[DebuggerBrowsable(DebuggerBrowsableState.Never)]
		public ItemCulture lang
		{
			get { return this.culture; }
			set { this.culture = value; }
		}
		/// 
		///////////////////////////////////////////////////////////////////////


		public new Object Items
		{
			get { return this; }
			set
			{
				IReadOnlyList<IString> rol;
				IEnumerable<IString> ie;
				IEnumerable<String> ies;
				IActiveObj<IString> ao;
				IActiveObj<String> aos;

				if ((rol = value as IReadOnlyList<IString>) != null)
				{
					base.Items = rol;
				}
				else if ((ie = value as IEnumerable<IString>) != null)
				{
					var e = ie.GetEnumerator();
					while (e.MoveNext())
						base.Add(e.Current);
				}
				else if ((ies = value as IEnumerable<String>) != null)
				{
					var e = ies.GetEnumerator();
					while (e.MoveNext())
						base.Add(new StringItem(this, e.Current));
				}
				else if ((ao = value as IActiveObj<IString>) != null)
				{
					if (this.Trace == ao.Trace)
						ao._set_trace(this);
					var arr = ao.ToArrayWait();

					IIdentity trace;
					for (int i = 0; i < arr.Length; i++)
						if ((trace = arr[i].Trace) == null || trace is SysObj)
							arr[i]._set_trace(this);
					base.Items = arr;
				}
				else if ((aos = value as IActiveObj<String>) != null)
				{
					var arr = aos.ToArrayWait();
					for (int i = 0; i < arr.Length; i++)
						base.Add(new StringItem(this, arr[i]));
				}
				else
				{
					throw new ArgumentTypeException();
				}

				int ix = 0;
				foreach (var it in base.Items)
					PP.ItemIndex.SetValue(it, ix++);
			}
		}
	};


	///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	/// <summary>
	/// 
	/// </summary>
	///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	[ContentProperty("Filename")]
	public class TextFileLoader : m_observable<String, IItem>,
		ρρFilename
	{
		public TextFileLoader(IRtParent parent, String filename, int i_skip, int i_take)
			: base(parent, filename)
		{
			this.c_skip = i_skip;
			this.c_take = i_take;
		}
		public TextFileLoader(IRtParent parent, String filename, int i_skip)
			: this(parent, filename, i_skip, int.MaxValue)
		{
		}
		public TextFileLoader(IRtParent parent, String filename)
			: this(parent, filename, 0)
		{
		}
		public TextFileLoader(IRtParent parent)
			: this(parent, default(String))
		{
		}

		///////////////////////////////////////////////////////////////////////
		/// 
		public String Filename
		{
			get { return this.t0; }
			set { this.t0 = value; }
		}
		/// 
		///////////////////////////////////////////////////////////////////////


		///////////////////////////////////////////////////////////////////////
		/// 
		int c_skip;
		public int SkipItems { get { return c_skip; } set { c_skip = value; } }
		/// 
		///////////////////////////////////////////////////////////////////////


		///////////////////////////////////////////////////////////////////////
		/// 
		int c_take;
		public int TakeItems { get { return c_take; } set { c_take = value; } }
		/// 
		///////////////////////////////////////////////////////////////////////

		protected override void start(String filename)
		{
			var fi = DirectoryPathSet.FindFileInfo(parent, filename);
			if (fi == null)
				throw new FileNotFoundException(filename);

			using (StreamReader sw = new StreamReader(fi.OpenRead()))
			{
				String line;
				for (int ix = -1, c = 0; (line = sw.ReadLine()) != null && c < c_take; )
				{
					if ((line = line.Trim()).Length == 0 || line[0] == '#')
						continue;

					if (++ix >= c_skip)
					{
						_item(extract_item(ix, line.Split(Charset.tab)));
						c++;
					}
				}
			}
			_remove_task();
		}

		Item extract_item(int ix, String[] cols)
		{
			var it = new Item(SysObj.Instance);

			PP.ItemIndex.SetValue(it, ix);

			int _tmp, i_col = 0;

			if (cols.Length > 1 && int.TryParse(cols[i_col++], out _tmp))
				PP.ExternalId.SetValue(it, _tmp);

			String txt = it.Text = cols[i_col++].Trim(Charset.dq);

			if (alib.String.Thai._string_thai_ext.ContainsThai(txt))
				it.ItemCulture = new ItemCulture(30);
			else
				it.ItemCulture = new ItemCulture(1033);

			if (i_col < cols.Length && int.TryParse(cols[i_col++].Trim(), out _tmp))
				P.ExpectedDerivationCount.SetValue(it, _tmp);

			if (i_col < cols.Length)
				it.Translations.Add(new StringItem(this, cols[i_col++]));

			return it;
		}
	};
}
